/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.merak.core.configuration;

import java.io.File;

import org.apache.commons.digester.Digester;
import org.merak.core.configuration.plugin.PluginSet;
import org.merak.core.configuration.plugin.Provider;
import org.merak.core.configuration.plugin.Service;
import org.merak.core.configuration.web.mvc.BusinessSettings;
import org.merak.core.configuration.web.mvc.ControlSettings;
import org.merak.core.configuration.web.mvc.ExceptionSettings;
import org.merak.core.configuration.web.mvc.SecuritySettings;
import org.merak.core.configuration.web.mvc.ViewSettings;
import org.merak.core.configuration.web.mvc.WebMVC;
import org.merak.core.model.parameter.Property;

public class XMLConfigurator {

	//~ Methods //////////////////////////////////////////////////////////////////
	//****************************************************************************
	public Configuration load(File inputFile) {

		if ( !inputFile.exists() ) {
			throw new RuntimeException("Cannot configure from missing file: "+inputFile);
		}

		try {
			// Create a XML parser
			Digester digester = new Digester();
			digester.setValidating( false );

			// Load head configurations
			digester.addObjectCreate ( "configuration", Configuration.class  );
			digester.addBeanPropertySetter( "configuration/name", "name" );
			digester.addBeanPropertySetter( "configuration/description", "description" );

			// Load Content
			this.loadPropertySet(digester);
			this.loadPlugins(digester);
			this.loadWebMVC(digester);

			// Return a configuration object
			return (Configuration) digester.parse(inputFile);
		}
		catch( Exception e ) {
			throw new RuntimeException(e);
		}

	}
	//****************************************************************************
	private void loadPropertySet(Digester digester) {

		// Load property set
		digester.addObjectCreate("configuration/PropetySet/property", Property.class);
		digester.addSetProperties("configuration/PropetySet/property", "name" , "name");
		digester.addCallMethod("configuration/PropetySet/property", "setValue", 0);
		digester.addCallParam("mconfiguration/PropetySet/property", 0);
		digester.addSetNext( "configuration/PropetySet/property", "addProperty" );

		// Load system property set
		digester.addObjectCreate("configuration/PropetySet/System/property", Property.class);
		digester.addSetProperties("configuration/PropetySet/System/property", "name" , "name");
		digester.addCallMethod("configuration/PropetySet/System/property", "setValue", 0);
		digester.addCallParam("mconfiguration/PropetySet/System/property", 0);
		digester.addSetNext( "configuration/PropetySet/System/property", "addSystemProperty" );

	}
	//****************************************************************************
	private void loadPlugins(Digester digester) {

		// Load PluginSets
		digester.addObjectCreate ( "configuration/PluginSet", PluginSet.class);
		digester.addSetProperties( "configuration/PluginSet" );
		digester.addSetNext("configuration/PluginSet", "addServiceSet");
		// Load Services
		digester.addObjectCreate(  "configuration/PluginSet/service",Service.class);
		digester.addSetProperties( "configuration/PluginSet/service","provider","providerClass");
		digester.addSetNext( "configuration/PluginSet/service", "addService" );
		// Load Providers
		digester.addObjectCreate ( "configuration/PluginSet/service/provider", Provider.class);
		digester.addSetProperties( "configuration/PluginSet/service/provider", "class" , "clazz");
		digester.addSetNext( "configuration/PluginSet/service/provider", "addProvider" );

	}
	//****************************************************************************
	private void loadWebMVC(Digester digester) {

		// Load MVC settings
		digester.addObjectCreate ( "configuration/WebMVC", WebMVC.class);
		digester.addSetNext("configuration/WebMVC", "setWebMVC");

		// Load Control settings
		digester.addObjectCreate( "configuration/WebMVC/Control", ControlSettings.class);
		digester.addSetNext("configuration/WebMVC/Control", "setControl");

		// Load Business settings
		digester.addObjectCreate( "configuration/WebMVC/Control/Business", BusinessSettings.class);
		digester.addSetProperties("configuration/WebMVC/Control/Business");
		digester.addSetNext("configuration/WebMVC/Control/Business", "setBusiness");

		// Load Security settings
		digester.addObjectCreate( "configuration/WebMVC/Control/Security", SecuritySettings.class);
		digester.addSetProperties("configuration/WebMVC/Control/Security");
		digester.addSetNext("configuration/WebMVC/Control/Security", "setSecurity");

		// Load Exception settings
		digester.addObjectCreate( "configuration/WebMVC/Control/Exceptions", ExceptionSettings.class);
		digester.addSetProperties( "configuration/WebMVC/Control/Exceptions/NoAuthentication","business","noAuthenticationLogic");
		digester.addSetProperties( "configuration/WebMVC/Control/Exceptions/NoAuthorization" ,"business","noAuthorizationLogic");
		digester.addSetProperties( "configuration/WebMVC/Control/Exceptions/ExpiredSession"  ,"business","expiredSessionLogic");
		digester.addSetProperties( "configuration/WebMVC/Control/Exceptions/ExecutionError"  ,"business","executionErrorLogic");
		digester.addSetNext("configuration/WebMVC/Control/Exceptions", "setExceptions");

		// Load View settings
		digester.addObjectCreate( "configuration/WebMVC/View", ViewSettings.class);
		digester.addSetProperties("configuration/WebMVC/View");
		digester.addSetNext("configuration/WebMVC/View", "setView");

	}
	//****************************************************************************

}
